﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.SharePoint;
using System.Collections;
using System.IO;

namespace ContentMigrator
{
    public partial class frmFileSystem : Form
    {
        private SPWeb moRootWeb = null;
        private SPList moCurrentLib = null;
        private SPWeb moCurrentWeb = null;
        private Hashtable mhtChoiceValues = new Hashtable();
        private bool mbAllowUserAdd;
        public frmFileSystem()
        {
            InitializeComponent();
        }
        #region METHODS
        private void ResizeListColumns(ListBox mylist)
        {
            try
            {
                //Resize column width to widest item
                int maxsize = 0;
                //const float COL_SPACING = 5;
                string text = string.Empty;
                foreach (object myitem in mylist.Items)
                {
                    if (myitem.ToString().Length > maxsize)
                    {
                        maxsize = myitem.ToString().Length;
                        text = myitem.ToString();
                    }
                }

                lstFiles.ColumnWidth = Convert.ToInt32(MeasureStringWidth(text, lstFiles.Font.Name, lstFiles.Font.Size));
            }
            catch (Exception)
            {
                
                throw;
            }
        }
        private float MeasureStringWidth(string Text, string FontName, float FontSize)
        {
            Bitmap b;
            Graphics g;
            Font f = new Font(FontName, FontSize);

            //Compute the string dimensions in the given font
            b = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            g = Graphics.FromImage(b);
            SizeF stringSize = g.MeasureString(Text, f);
            g.Dispose();
            b.Dispose();
            return stringSize.Width;
        }
        #endregion 

        #region EVENT HANDLERS
        void lstFiles_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
        {
            e.Effect = DragDropEffects.Copy;
        }
        void lstFiles_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
        {
            try
            {
                if (e.Data.GetDataPresent("FileDrop"))
                {
                    string[] files = (string[])e.Data.GetData("FileDrop");
                    foreach (string myitem in files)
                        if (Directory.Exists(myitem)) {
                            ArrayList arl = new ArrayList();
                            StaticMethods.ExpandFolderToArrayList(myitem, arl);
                            foreach (string myfile in arl)
                            {
                                if (!lstFiles.Items.Contains(myfile))
                                    lstFiles.Items.Add(myfile);
                            }
                        }
                        else
                            if (File.Exists(myitem))
                                if (!lstFiles.Items.Contains(myitem))
                                    lstFiles.Items.Add(myitem);
                }
                ResizeListColumns(lstFiles);
                lblCount.Text = lstFiles.Items.Count.ToString() + " items";
            }
            catch (Exception ex)
            {

                throw new Exception("Drag/drop error: " + ex.Message);
            }
        }
        private void frmFileSystem_Load(object sender, EventArgs e)
        {
            try
            {
                moRootWeb = StaticMethods.GetWebFromUrl(new Uri(Properties.Settings.Default.RootWeb));
                StaticMethods.EnumSitesToComboBox(moRootWeb, cbxSite);
                StaticMethods.EnumLibrariesToComboBox(moCurrentWeb, cbxLibrary);
                StaticMethods.EnumFoldersToComboBox(moCurrentLib, cbxFolder);
            }
            catch (Exception ex)
            {
                
                throw ex;
            }
        }
        private void btnAddFile_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Multiselect = true;
                ofd.InitialDirectory = "C:\\";
                ofd.ShowDialog();

                if (ofd.FileNames.Length > 0)
                foreach (string myfile in ofd.FileNames)
                {
                    if (!lstFiles.Items.Contains(myfile))
                        lstFiles.Items.Add(myfile);
                }
                ResizeListColumns(lstFiles);
                lblCount.Text = lstFiles.Items.Count.ToString() + " items";
            }
            catch (Exception ex)
            {
                
                MessageBox.Show(ex.Message,"ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void cbxSite_SelectedIndexChanged(object sender, EventArgs e)
        {
            moCurrentWeb = StaticMethods.GetWebFromUrl(new Uri(cbxSite.Text));
            StaticMethods.EnumLibrariesToComboBox(moCurrentWeb, cbxLibrary);
        }
        private void cbxLibrary_SelectedIndexChanged(object sender, EventArgs e)
        {
            moCurrentLib = moCurrentWeb.Lists[cbxLibrary.Text];
            StaticMethods.EnumContentTypesToComboBox(moCurrentLib,cbxContentTypes);
            StaticMethods.EnumFoldersToComboBox(moCurrentLib,cbxFolder);
        }
        private void cbxFolder_SelectedIndexChanged(object sender, EventArgs e)
        {

        }
        private void cbxContentTypes_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cbxContentTypes.SelectedIndex > -1)
                StaticMethods.EnumContentTypeFieldsToDataGridView(moCurrentLib, cbxContentTypes.Text, dgvMetadata, mhtChoiceValues);

            btnUpload.Enabled = (dgvMetadata.Rows.Count > 0);
        }
        void dgvMetadata_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            try
            {
                if (e.Control.GetType() == typeof(DataGridViewComboBoxEditingControl))
                {
                    //get reference to editing control
                    DataGridViewComboBoxEditingControl cbo = e.Control as DataGridViewComboBoxEditingControl;

                    //if we're editing a row that represents a choice-type column, we want
                    //to 
                    //1. load cmbChoiceEditor with the appropriate values
                    //2. position and size cmbChoiceEditor
                    //3. hide the normal editing control
                    //4. show cmbChoiceEditor


                    string metacol = dgvMetadata.Rows[dgvMetadata.CurrentRow.Index].Cells["Key"].Value.ToString();
                   
                    if (mhtChoiceValues.Contains(metacol))
                    {
                        StaticMethods.SetupGridDropdownColumn((ArrayList)mhtChoiceValues[metacol], cbo,true);
                        //do not allow user to add their own value
                        cbo.DropDownStyle = ComboBoxStyle.DropDownList;
                        mbAllowUserAdd = false;
                        cbo.Validating += new CancelEventHandler(cbo_Validating);
                    }
                    else
                    {
                        //allow user to enter their own value
                        cbo.Items.Clear();
                        cbo.DropDownStyle = ComboBoxStyle.DropDown;
                        mbAllowUserAdd = true;
                        cbo.Validating += new CancelEventHandler(cbo_Validating);
                    }
                }
            }
            catch (Exception ex)
            {

                throw new Exception("dgvMetadata_EditingControlShowing:" + ex.Message);
            }

        }
        void dgvMetadata_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
        }
        void cbo_Validating(object sender, CancelEventArgs e)
        {

            try
            {
                DataGridViewComboBoxEditingControl cbo = sender as DataGridViewComboBoxEditingControl;

                DataGridView grid = cbo.EditingControlDataGridView;
                DataGridViewComboBoxColumn cboCol = grid.Columns[grid.CurrentCell.ColumnIndex] as DataGridViewComboBoxColumn;
                object value = cbo.Text;


                if (mbAllowUserAdd)
                {
                    // Add value to list if not there


                    if (cbo.Items.IndexOf(value) == -1)
                    {



                        // Must add to both the current combobox as well as the template, to avoid duplicate entries...


                        cbo.Items.Add(value);


                    }
                }
                grid.CurrentCell.Value = value;
                cboCol.Items.Add(value);
            }
            catch (Exception)
            {

            }


        }
        private void btnUpload_Click(object sender, EventArgs e)
        {
            try
            {
                StringBuilder Report = new StringBuilder();
#if DEBUG
                StringBuilder Log = new StringBuilder();
#endif
                SPFolder folder = null;

                Cursor.Current = Cursors.WaitCursor;
                this.Enabled = false;
                progressBar1.Visible = true;
                progressBar1.Value = 0;
                progressBar1.Maximum = lstFiles.Items.Count;

                // Upload each file with the specified metadata information
                foreach (object myitem in lstFiles.Items)
                {
                    try
                    {
#if DEBUG
                        Log.AppendLine("Top of main loop");
#endif
                        Hashtable properties = new Hashtable();

                        // Only properties that have been filled in will be added to the new file
                        //foreach (DataRow row in dtMetadata.Rows)
#if DEBUG
                        Log.AppendLine("Before metadata loop");
#endif
                        for (int i = 1; i < dgvMetadata.Rows.Count; i++)
                        {
#if DEBUG
                            Log.AppendLine("Top of metadata loop");
#endif
                            DataGridViewRow row = dgvMetadata.Rows[i];
#if DEBUG
                            Log.AppendLine("row set");
#endif
                            string key = row.Cells["Key"].Value.ToString();
                            if (!StaticMethods.ValidateFieldValue(moCurrentLib,cbxContentTypes.Text,key, row.Cells["Value"].Value))
                            {
                                throw new Exception("Invalid value specified for field " + key + ".");
                            }

                            if (row.Cells["Value"].Value != null)
                            {
#if DEBUG
                                Log.AppendLine("Metadata value not empty:" + row.Cells["Value"].Value.ToString());
#endif
                                properties.Add(row.Cells["Key"].Value.ToString(), row.Cells["Value"].Value.ToString());
                            } 
                        }
#if DEBUG
                        Log.AppendLine("After metadata loop");
#endif


                            string path = myitem.ToString();
                            string filename = string.Empty;
                            byte[] fileContents = StaticMethods.GetFileBytes(path);
#if DEBUG
                            Log.AppendLine("File bytes retrieved: " + fileContents.Length.ToString());
#endif

                            if (path.ToLower().Contains("http") || path.ToLower().Contains("ftp"))
                                filename = path.Substring(path.LastIndexOf("/") + 1);
                            else
                                filename = path.Substring(path.LastIndexOf("\\") + 1);

                            //retrieve or create destination folder
                            string foldername;
                            if (cbxFolder.Text.ToLower() == "<root>")
                            {
                                //use root folder of library
                                foldername = moCurrentLib.RootFolder.Url;
                            }
                            else
                            {
                                //existing subfolder
                                foldername = moCurrentLib.RootFolder.ServerRelativeUrl + "/" + cbxFolder.Text;
                            }

                            if (chkCreateFolder.Checked == true)
                            {
                                //strip drive letter from path
                                string filesysfolder =   path.Replace(filename,"").Replace(path.Substring(0,2),"");
                                
                                //create folder structure in target library
                                folder = StaticMethods.GetFolderTree(moCurrentWeb,moCurrentLib,filesysfolder,true);
                            } else {
                                folder = moCurrentWeb.GetFolder(foldername);
                            }

#if DEBUG
                            Log.AppendLine("folder retrieved");
#endif
 
                            if (!folder.Exists)
                                throw new Exception("Could not connect to folder '" + cbxFolder.SelectedText + "'");

                            //clean filename
                            filename = StaticMethods.CleanFilename(filename);

                            //add file to library
                            SPFile myfile = folder.Files.Add(filename, fileContents, chkOverwrite.Checked);
                            if (!myfile.Exists)
                                throw new Exception("File not added to folder");
#if DEBUG
                            Log.AppendLine("File added to folder");
                            Log.AppendLine("Setting metadata fields as follows:");
#endif
                            //fill metadata fields
                            foreach (string mykey in properties.Keys)
                            {
#if DEBUG
                                Log.AppendLine(mykey + "=" + properties[mykey].ToString());
#endif
                                string val = properties[mykey].ToString();
                                if (mykey == "FileLeafRef")
                                {
                                    val = StaticMethods.CleanFilename(val);
                                }
                                myfile.Item[mykey] = val;
                            }
                            //update fields
                            myfile.Item.Update();
#if DEBUG
                            Log.AppendLine("File metadata fields updated");
#endif
                    }
                    catch (Exception ex)
                    {
                        Report.AppendLine(myitem.ToString() + "\t" + ex.Message);
#if DEBUG
                        string logfile = System.Environment.CurrentDirectory + "\\ImportLog_" + DateTime.Now.ToString("MMddyyhhmmss") + ".txt";
                        if (File.Exists(logfile) == true)
                        {
                            File.Delete(logfile);
                        }
                        File.WriteAllText(logfile, Log.ToString());
                        string errfile = StaticMethods.WriteErrFile(Report);
                        MessageBox.Show("DEBUG BUILD: Fatal error. Check the log file " + logfile + " and error file " + errfile + ".\r\nApplication will now terminate.", "DEBUG: ERROR", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        this.Close();

#endif
                    }
                    progressBar1.Value += 1;
                    progressBar1.Refresh();
                    Application.DoEvents();
                }

                progressBar1.Visible = false;
                Cursor.Current = Cursors.Default;
                this.Enabled = true;

                if (Report.ToString() != string.Empty)
                {
                    string errfile = StaticMethods.WriteErrFile(Report);
                    MessageBox.Show("Completed with errors:\r\nSee error file for details.", "COMPLETED WITH ERRORS", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                else
                    MessageBox.Show("Completed.", "COMPLETED", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                Cursor.Current = Cursors.Default;
                this.Enabled = true;
                progressBar1.Visible = false;
                MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }
        private void btnAddFolder_Click(object sender, EventArgs e)
        {
            try
            {
                FolderBrowserDialog fbd = new FolderBrowserDialog();
                fbd.RootFolder = Environment.SpecialFolder.MyComputer;
                fbd.ShowDialog();

                if (fbd.SelectedPath != string.Empty) {
                    ArrayList files = new ArrayList();
                    StaticMethods.ExpandFolderToArrayList(fbd.SelectedPath, files);
                    foreach (string myfile in files)
                    {
                        if (!lstFiles.Items.Contains(myfile))
                            lstFiles.Items.Add(myfile);
                    }
                    ResizeListColumns(lstFiles);
                    lblCount.Text = lstFiles.Items.Count.ToString() + " items";
                }
            }
            catch (Exception ex)
            {
                
               MessageBox.Show("Error adding folder: " + ex.Message);
            }
        }
        private void btnClear_Click(object sender, EventArgs e)
        {
            if (lstFiles.Items.Count > 0)
            {
                lstFiles.Items.Clear();
                lblCount.Text = lstFiles.Items.Count.ToString() + " items";
            }

        }
        private void btnRemove_Click(object sender, EventArgs e)
        {
            try
            {
                if (lstFiles.SelectedIndices.Count > 0)
                {      
                    foreach (int myidx in lstFiles.SelectedIndices)
                    {
                        lstFiles.Items.RemoveAt(myidx);
                    }
                    ResizeListColumns(lstFiles);
                    lblCount.Text = lstFiles.Items.Count.ToString() + " items";
                }
            }
            catch (Exception ex)
            {
                
                MessageBox.Show("Error removing list item(s): " + ex.Message);
            }
        }
        #endregion
    }
}
